﻿using System;
using System.Linq;

namespace TLD_NN
{
    public class Normalizer
    {
        /// <summary>
        /// Normalizes data from a uint array to a double array on the interval lowest to highest
        /// </summary>
        /// <param name="data">input data</param>
        /// <param name="lowest">lowest value of the normalized range</param>
        /// <param name="highest">highest value of the normalized range</param>
        /// <returns>normalized data</returns>
        public double[] Normalize(uint[] data, double lowest, double highest)
        {
            if (lowest > highest)
            {
                throw new ArgumentException("lowest cannot be higher than highest when normalizing");
            }

            int items = data.Length;
            double[] normalized = new double[items];
            
            //in case of empty array
            if (items == 0)
            {
                return normalized;
            }

            uint max = data.Max();
            uint min = data.Min();
            
            //if the array has only similar values or the range is a point
            if (min == max || lowest == highest)
            {
                for (int i = 0; i < data.Length; i++)
                {
                    normalized[i] = lowest;
                }
                return normalized;
            }

            double factor = (highest - lowest) / (max - min);
            double offset = max * factor - highest;
            for (int i = 0; i < data.Length; i++)
            {
                double norm = data[i] * factor - offset;
                //in case of rounding errors
                if (norm > highest)
                {
                    normalized[i] = highest;
                }
                //in case of rounding errors
                else if (norm < lowest)
                {
                    normalized[i] = lowest;
                }
                else
                {
                    normalized[i] = norm;
                }
            }
            return normalized;
        }

    }
}
